package java_thinking.unit_14._14_8;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @Description :如果用接口取代具体类，
 *               那么就可以使用DynamicProxy来自动创建空对象，代码如下：
 * @author: cww
 * @DateTime: 2019-03-31 20:05
 */
interface Operation {
    String description();
    void command();
}

/**
 * Robot接口
 */
interface Robot {
    String name();
    String model();
    List<Operation> operations();
}

/**
 * SnowRemovalRobot扫雪机器人实现类
 */
class SnowRemovalRobot implements Robot {
    private String name;
    public SnowRemovalRobot(String name) {
        this.name = name;
    }
    @Override
    public String name() {
        return name;
    }
    @Override
    public String model() {
        return "SnowBot Series 11";
    }
    @Override
    public List<Operation> operations() {
        return Arrays.asList(
                new Operation() {
                    @Override
                    public String description() {
                        return name + " can shovel snow";
                    }
                    @Override
                    public void command() {
                        System.out.println(name + " shoveling snow");
                    }
                },
                new Operation() {
                    @Override
                    public String description() {
                        return name + " can chip ice";
                    }
                    @Override
                    public void command() {
                        System.out.println(name + " chipping ice");
                    }
                }
        );
    }
}

/**
 *空机器人代理处理器：
 */
class NullRobotProxyHandler implements InvocationHandler {
    private String nullName;
    private Robot proxied = new NRobot();
    NullRobotProxyHandler(Class<? extends Robot> type) {
        nullName = type.getSimpleName() + " NullRobot";
    }
    private class NRobot implements Null, Robot {
        @Override
        public String name() { return nullName; }
        @Override
        public String model() { return nullName; }
        @Override
        public List<Operation> operations() {
            return Collections.emptyList();
        }
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(proxied, args);
    }
}

class NullRobot {
    public static Robot newNullRobot(Class<? extends Robot> type) {
        return (Robot) Proxy.newProxyInstance(
                NullRobot.class.getClassLoader(),
                new Class[]{ Null.class, Robot.class },
                new NullRobotProxyHandler(type));
    }
    public static void test(Robot r) {
        if(r instanceof Null)
            System.out.println("[Null Robot]");
        System.out.println("Robot name: " + r.name());
        System.out.println("Robot model: " + r.model());
        for(Operation operation : r.operations()) {
            System.out.println(operation.description());
            operation.command();
        }
    }
    public static void main(String[] args) {
        Robot[] bots = {new SnowRemovalRobot("SnowBee"),
                newNullRobot(SnowRemovalRobot.class)
        };
        for(Robot bot : bots)
            NullRobot.test(bot);
    }
}